/**
 * 
 */
package com.cmcc.awareness;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.pcap4j.packet.Packet;

import com.cmcc.awareness.util.CommonUtils;

/**
 * @author Amish
 * @date 2018年12月7日 下午7:13:40
 * 
 * 单字节比较运算符表达式：c
 * 
 * eg:
 *  {c|11|0x0aa}{l|0|17}
	{c|11|0x167}{l|0|18}
	{c|11|0x267}{l|0|18}
	{c|-11|0x20a}{l|0|18}
 */
public class ProtoDatProtocolFeatureCodeElement_c implements ProtoDatProtocolFeatureCodeElement {
	private static Logger logger = LogManager.getLogger(ProtoDatProtocolFeatureCodeElement_c.class);

	String initialStr;

	String offset;
	String operator;
	String hexValue;
	
	public String appName;
	public String protocolType;
	public ProtoDatProtocolFeatureCodeElement_c(String appName,String protocolType){
		this.appName = appName;
		this.protocolType = protocolType;
	}
	
	@Override
	public String getType() {
		// TODO Auto-generated method stub
		return null;
	}


	@Override
	public boolean distinguish(String protocolType,jpcap.packet.Packet packet) {
		try{
			byte[] data = packet.data;
			
			int offsetInt = Integer.valueOf(offset);
			if(data ==null || data.length == 0)
				return false;
			
			if(offsetInt>=0 && data.length < offsetInt + 1 )
				return false;
						
		    if(offsetInt < 0 && data.length < Math.abs(offsetInt))
		    	return false;
			
			String dataHexValue;
			if(offsetInt < 0){//偏移量为负数时，表示从尾部数，第|offset|个字节
				dataHexValue = CommonUtils.byteToHexString(data[offsetInt + data.length]);				
			}else{
				dataHexValue = CommonUtils.byteToHexString(data[offsetInt]);
			}
			
			int hexValueInt = Integer.parseInt(hexValue, 16);
			int dataHexValueInt = Integer.parseInt(dataHexValue, 16);
			
			switch(operator){
			case "0"://!=
				if(dataHexValueInt != hexValueInt){
					return true;
				}
				return false;
			case "1"://>
				if(dataHexValueInt > hexValueInt){
					return true;
				}
				return false;
			case "2"://<
				if(dataHexValueInt < hexValueInt){
					return true;
				}
				return false;
			default:
				return false;
			}
			
		}catch(Exception e){
			e.printStackTrace();
			System.out.println("Distinguish Exception -- <"+this.appName+">"+"<"+this.protocolType+"> : "+this.toString());
			return false;
		}
	}


	@Override
	public void parseSelf(String element) {
		try{			
			this.initialStr = element;
			String[] str = element.split("\\|");
			this.offset = str[1];
			
			if(str[2].length() == 5){//{c|0|0x003}
				this.operator = str[2].substring(2,3);
				this.hexValue = str[2].substring(3);
			}else if(str[2].length() == 6){//{c|0|0x0003}
				this.operator = str[2].substring(3,4);
				this.hexValue = str[2].substring(4);
			}else{
				//do nothing
			}
		}catch(Exception e){
			e.printStackTrace();
		}

	}
	
	public String toString(){
		return "{"+initialStr+"}";
	}

	@Override
	public boolean distinguish(String protocolType, Packet packet) {
		try{
			byte[] data = packet.getRawData();
			
			int offsetInt = Integer.valueOf(offset);
			if(data ==null || data.length == 0)
				return false;
			
			if(offsetInt>=0 && data.length < offsetInt + 1 )
				return false;
						
		    if(offsetInt < 0 && data.length < Math.abs(offsetInt))
		    	return false;
			
			String dataHexValue;
			if(offsetInt < 0){//偏移量为负数时，表示从尾部数，第|offset|个字节
				dataHexValue = CommonUtils.byteToHexString(data[offsetInt + data.length]);				
			}else{
				dataHexValue = CommonUtils.byteToHexString(data[offsetInt]);
			}
			
			int hexValueInt = Integer.parseInt(hexValue, 16);
			int dataHexValueInt = Integer.parseInt(dataHexValue, 16);
			
			switch(operator){
			case "0"://!=
				if(dataHexValueInt != hexValueInt){
					return true;
				}
				return false;
			case "1"://>
				if(dataHexValueInt > hexValueInt){
					return true;
				}
				return false;
			case "2"://<
				if(dataHexValueInt < hexValueInt){
					return true;
				}
				return false;
			default:
				return false;
			}
			
		}catch(Exception e){
			e.printStackTrace();
			System.out.println("Distinguish Exception -- <"+this.appName+">"+"<"+this.protocolType+"> : "+this.toString());
			return false;
		}
	}

}
